package com.leetcode.weekly.contest.no233th;

import java.util.Comparator;
import java.util.PriorityQueue;

/**
 * @author 覃国强
 * @date 2021-03-21 10:50
 */
public class A02_积压订单中的订单总数 {

  public static void main(String[] args) {
    Solution solution = new Solution();
    int[][] orders = {
        {10,5,0},
        {15,2,1},
        {25,1,1},
        {30,4,0}
    };
    int number = solution.getNumberOfBacklogOrders(orders);
    System.out.println(number);
  }

  static
  class Solution {
    public int getNumberOfBacklogOrders(int[][] orders) {

      PriorityQueue<Order> buyOrders = new PriorityQueue<>((o1, o2) -> o2.price - o1.price);
      PriorityQueue<Order> sellOrders = new PriorityQueue<>(Comparator.comparingInt(o -> o.price));

      for (int[] orderValue : orders) {
        Order order = new Order(orderValue[0], orderValue[1], orderValue[2]);

        if (order.orderType == 0) {
          if (sellOrders.isEmpty()) {
            buyOrders.offer(order);
          } else {
            if(sellOrders.peek().price <= order.price) {
              while (!sellOrders.isEmpty() && sellOrders.peek().price <= order.price && order.amount > 0) {
                if (order.amount >= sellOrders.peek().amount) {
                  order.amount -= sellOrders.peek().amount;
                  sellOrders.poll();
                } else {
                  sellOrders.peek().amount -= order.amount;
                  order.amount = 0;
                }
              }
              if (order.amount > 0) {
                buyOrders.offer(order);
              }
            } else {
              buyOrders.offer(order);
            }
          }
        } else {
          if (buyOrders.isEmpty()) {
            sellOrders.offer(order);
          } else {
            if (buyOrders.peek().price >= order.price) {
              while (!buyOrders.isEmpty() && buyOrders.peek().price >= order.price
                  && order.amount > 0) {
                if (order.amount >= buyOrders.peek().amount) {
                  order.amount -= buyOrders.peek().amount;
                  buyOrders.poll();
                } else {
                  buyOrders.peek().amount -= order.amount;
                  order.amount = 0;
                }
              }
              if (order.amount > 0 ){
                sellOrders.offer(order);
              }
            } else {
              sellOrders.offer(order);
            }
          }
        }
      }

      int result = 0;
      int p = 10_0000_0000 + 7;
      for (Order order : buyOrders) {
        result = (result % p + order.amount % p) % p;
      }
      for (Order order : sellOrders) {
        result = (result % p + order.amount % p) % p;
      }
      return result;
    }

    private static class Order {

      int price;

      int amount;

      int orderType;

      public Order(int price, int amount, int orderType) {
        this.price = price;
        this.amount = amount;
        this.orderType = orderType;
      }
    }

  }

}
